package com.itlangzi.mybatis.dialect;

import com.itlangzi.mybatis.dialect.helper.DialectEnum;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Optional;
import java.util.Set;

/**
 * 方言处理工厂
 */
public class DialectFactory {
	
	private static Logger logger = LoggerFactory.getLogger(DialectFactory.class);

	private static final Map<DialectEnum, Dialect> DIALECT_MAP = new HashMap<>();

	private DialectFactory(){}
	static {
		// MySQL | Mariadb
		try {
			Class.forName("org.mariadb.jdbc.Driver");
			DIALECT_MAP.put(DialectEnum.MYSQL, new MySQLDialect());
		} catch (ClassNotFoundException e) {
			try {
				Class.forName("com.mysql.cj.jdbc.Driver");
				DIALECT_MAP.put(DialectEnum.MYSQL, new MySQLDialect());
			} catch (ClassNotFoundException e1) {
				try {
					Class.forName("com.mysql.jdbc.Driver");
					DIALECT_MAP.put(DialectEnum.MYSQL, new MySQLDialect());
				} catch (ClassNotFoundException e2) {
					logger.debug("Not Found Any ( MySQL | Mariadb ) Driver");
				}
			}
		}
		// Oracle
		try {
			Class.forName("oracle.jdbc.driver.OracleDriver");
			DIALECT_MAP.put(DialectEnum.ORACLE, new OracleDialect());
		} catch (ClassNotFoundException e) {
			logger.debug("Not Found Any Oracle Driver");
		}
		// SQL Server
		try {
			Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
			DIALECT_MAP.put(DialectEnum.SQLSERVER, new SQLServer2012Dialect());
		} catch (ClassNotFoundException e) {
			logger.debug("Not Found Any SQL Server Driver");
		}
	}
	
	
	public static Dialect buildDialectFromJDBCURL(String jdbcUrl) {
		Map<DialectEnum, Dialect> dialectMap = DIALECT_MAP;

		Set<Entry<DialectEnum, Dialect>> entries = dialectMap.entrySet();
		
		Optional<Entry<DialectEnum, Dialect>> optional = entries.stream()
				.filter(entry -> {
					String dbName = entry.getKey().name().toLowerCase();
					return jdbcUrl.indexOf(":" + dbName + ":") > -1;
				}).findFirst();
		if (optional.isPresent()) {
			return optional.get().getValue();
		}
		return null;
	}
}
